home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Scope / Scope Disk #020 (199x)(Scope PD)(US)[WB].zip / Scope Disk #020 (199x)(Scope PD)(US)[WB].adf / VirusX15 / virusx.c < prev    next >
C/C++ Source or Header  |  1988-07-24  |  23KB  |  836 lines

  1.  
  2. /* VirusX - by Steve Tibbett
  3.  
  4.     The complete Virus Elimination System!
  5.  
  6.         Please - if you find a new virus, Send me a copy!
  7.         (And warn me it's on the disk!).  I want to keep
  8.         this program current.  (Feel free to put something
  9.         neat on the disk also!)
  10.  
  11.  
  12. History:
  13. --------
  14.  
  15.  A few weeks ago: V1.0 written.
  16. A few days later: V1.01 released - V1.0 wrote garbage when disk was Write Prot. 
  17.        27-Mar-88: V1.2 - Added Byte Bandit RAM detection, and disk detection.  
  18.           (Actually, it's well after Midnight - make that 28-Mar-88)
  19. Just after
  20. uploading V1.2
  21.      to Amic BBS: Realized I put the wrong version in the ARC file - Had to
  22.                   rename V1.2 to V1.21...
  23.  
  24.    June 15, 1988: Created V1.3 which was just V1.21 cleaned up, made a bunch smaller.
  25.  
  26.     July 8, 1988: Recieved Revenge virus Yesterday, disassembled it,
  27.                   and added it to VirusX 1.4.  Added ViewBoot and SCA check also.
  28.  
  29.    July 24, 1988: Recieved the Byte Warrior virus, added it.  V1.5
  30.  
  31.   Viruses Dealt With:
  32.  
  33.     Byte Bandit    - RAM and Disk checked, TD vector patched,
  34.               resident module destroyed, Interrupt
  35.               patched.
  36.     
  37.     SCA        - Disk checked, CoolCapture checked, fixed
  38.               if it points to a known SCA virus.
  39.  
  40.     Revenge        - DoIO patched, Interrupt patched, Disk
  41.               checked.
  42.  
  43.     Byte Warrior - 
  44.  
  45. */
  46.  
  47. #include <stdio.h>
  48. #include <exec/types.h>
  49. #include <intuition/intuition.h>
  50. #include <devices/bootblock.h>
  51. #include <devices/trackdisk.h>
  52. #include <exec/execbase.h>
  53.  
  54. /*  This stuff is for the detach module Manx provides, that's how
  55.     VirusX can be executed in the Startup Sequence and have the 
  56.     initial CLI window close without any problems. 
  57.  
  58.      (but not until I get a version of 1.3 that works with it)
  59.  
  60.     */
  61. /*
  62. long _stack = 16000;
  63. long _priority = 0;
  64. long _BackGroundIO = 0;
  65. char *_procname = "VirusX";
  66. */
  67.  
  68. /*
  69.  
  70.     Created with Aztec C V3.6a using 32 bit ints.
  71.  
  72.     (My makefile is included in the archive)
  73.  
  74.     No longer uses Precompiled Headers, so it should compile OK.
  75.  
  76. */
  77.  
  78. struct         Port         *diskport;    /* disk's port.*/
  79. struct         IOStdReq     *diskreq;    /* disk's IOStdReq */
  80. int        DisksChecked, 
  81.         DisksInstalled, 
  82.         VirusesFound;            /* for title bar info */
  83. char         titlebuffer[75];        /* Where tietie bar is kept */
  84.  
  85. /* Amount of boot code we've got bwlow (approx):  */
  86. #define BSIZE 40
  87.  
  88. char TDName[] = "trackdisk.device";    /* Saves space */
  89. char copystring[] = "(Copy Count on this disk: %d)"; /* Again, saves space */
  90.  
  91. int ChangeCount[4];        /* TD_CHANGECOUNT for all 4 drives */
  92. int LastSum;            /* Used in the checksumming */
  93. int CheckDrives;        /* Boolean, from the command line */
  94. int error;            /* sort of a temporary variable sort of */
  95.  
  96. unsigned char diskbuffer[3*512];/* Everything ends up in here. 
  97.                    I suppose I should have AllocMem'ed this,
  98.                    but it's SO easy this way 
  99.  
  100.             Note that this is 3*512, not 2*512.  The reason
  101.             for this is that I have heard that the SCA will
  102.             attempt to rewrite itself whenever it sees a Read
  103.             request of 1024 bytes... So I read 3 blocks.
  104.             */
  105.  
  106. /* Warning messages.  These messages get modified before being displayed
  107.    (Unless you DO have a DF9:) */
  108.  
  109. char TEXTPTR[] = "Danger:  The disk in DF9: is";
  110. char NBCTEXT[] = "Danger:  The disk in DF9: has";  /* What a waste, eh? */
  111. char CopyText[40];
  112.  
  113. /* This is a byte by byte copy of working boot block code.  Check it
  114.    out if you like.  This is what gets written back to the disk when you
  115.    ask VirusX to fix a disk. */
  116.  
  117. unsigned char bootblock[] = { 'D', 'O', 'S', 0, 
  118. 0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18, 
  119. 0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68, 
  120. 0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
  121. 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
  122. 0x00, 0x00};
  123.  
  124. struct TextAttr TxtAt_Plain = {    "topaz.font", 8, FS_NORMAL, FPF_ROMFONT};
  125.  
  126. /***  Non SCA warning requester IntuiText's ***/
  127. struct IntuiText Body2 = { 0, 1,  JAM2, 20,18, &TxtAt_Plain,
  128.     "Nonstandard Boot Code!", NULL };
  129. struct IntuiText Body1 = {
  130.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)NBCTEXT, &Body2 };
  131. struct IntuiText Pos = {
  132.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Remove it", NULL };
  133. struct IntuiText Neg = {
  134.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "Ignore it", NULL };
  135.  
  136. /***** SCA Danger Requester IntuiText's ******/
  137. struct IntuiText SCABody2 = {
  138.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "infected with an SCA Virus!!", NULL };
  139. struct IntuiText SCABody = {
  140.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)TEXTPTR, &SCABody2 };
  141. struct IntuiText SCAPos = {
  142.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Remove it", NULL };
  143. struct IntuiText SCANeg = {
  144.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "Ignore it", NULL };
  145.  
  146. /***** BBANDIT Requester IntuiText's ******/
  147. struct IntuiText BBDiskbody3 = {
  148.    0, 1,     JAM2,          20,30,        &TxtAt_Plain, CopyText, NULL };
  149. struct IntuiText BBDiskbody2 = {
  150.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "infected with the Byte Bandit VIRUS!", &BBDiskbody3};
  151. struct IntuiText BBDiskbody = {
  152.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)TEXTPTR, &BBDiskbody2 };
  153.  
  154. /***** Byte Warrior Requester IntuiText's ******/
  155. struct IntuiText ByteWarriorBody2 = {
  156.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "infected with the Byte Warrior VIRUS!", 0};
  157. struct IntuiText ByteWarriorBody = {
  158.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)TEXTPTR, &ByteWarriorBody2 };
  159.  
  160. /***** BBandit Notice - Removed from Memory ****/
  161. struct IntuiText BBMem2 = {
  162.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled.  See the", NULL};
  163. struct IntuiText BBMem1 = {
  164.    0, 1,     JAM2,          20,28,        &TxtAt_Plain,(UBYTE *) "documentation for more information!", &BBMem2 };
  165. struct IntuiText BBMem3 = {
  166.    0, 1,     JAM2,          20,8,        &TxtAt_Plain,(UBYTE *) "NOTICE:  The Byte Bandit VIRUS was found", &BBMem1 };
  167. struct IntuiText BBMPos = {
  168.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, " Thanks! ", NULL };
  169.  
  170. /***** Byte Warrior Notice - Removed from Memory ****/
  171. struct IntuiText ByteWarriorMem = {
  172.    0, 1,     JAM2,          20,8,        &TxtAt_Plain,(UBYTE *) "NOTICE:  The Byte Warrior VIRUS was found", &BBMem1 };
  173.  
  174. /***** Revenge on Disk Requester IntuiText's ******/
  175. struct IntuiText RevDiskbody3 = {
  176.    0, 1,     JAM2,          20,30,        &TxtAt_Plain, CopyText, NULL };
  177. struct IntuiText RevDiskbody2 = {
  178.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "infected with the -Revenge- VIRUS!", &RevDiskbody3};
  179. struct IntuiText RevDiskbody = {
  180.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)TEXTPTR, &RevDiskbody2 };
  181.  
  182. /***** Revenge Notice - Removed from Memory ****/
  183. struct IntuiText RevMem = {
  184.    0, 1,     JAM2,          20,8,        &TxtAt_Plain,(UBYTE *) "NOTICE:  The Revenge! VIRUS was found", &BBMem1 };
  185.  
  186. /***** Revenge Notice - Removed from Memory ****/
  187. struct IntuiText SCAMem = {
  188.    0, 1,     JAM2,          20,8,        &TxtAt_Plain,(UBYTE *) "NOTICE:  An SCA-type Virus was found", &BBMem1 };
  189.  
  190. /***** Write Protect Error Requester IntuiText's ******/
  191. struct IntuiText ERRBody2 = {
  192.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL };
  193. struct IntuiText ERRBody = {
  194.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)"DISK ERROR:  Disk is", &ERRBody2 };
  195. struct IntuiText ERRPos = {
  196.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Retry", NULL };
  197. struct IntuiText ERRNeg = {
  198.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "Cancel", NULL };
  199.  
  200. /***** Rewrite block?  Really? ******/
  201. struct IntuiText REWBody3 = {
  202.    0, 1,     JAM2,          20,28,        &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL };
  203. struct IntuiText REWBody2 = {
  204.    0, 1,     JAM2,          20,18,        &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3};
  205. struct IntuiText REWBody = {
  206.    0, 1,        JAM2,          20, 8, &TxtAt_Plain,      (UBYTE *)"Are you sure you want to", &REWBody2 };
  207. struct IntuiText REWPos = {
  208.    0, 1,     JAM2,           7,3,        &TxtAt_Plain, "Yes", NULL };
  209. struct IntuiText REWNeg = {
  210.    0, 1,    JAM2,           7,3,        &TxtAt_Plain, "No!", NULL };
  211.  
  212. struct IntuitionBase *IntuitionBase;
  213. struct GfxBase *GfxBase;
  214. struct Window *LittleWindow;
  215. struct IntuiMessage *Message;
  216. struct RastPort *RP;
  217.  
  218. int Keepgoing;        /* a boolean flag.  it's false when we want out. */
  219. int x, y, i;        /* left over from my using Basic */
  220.  
  221. /*** The Newwindow Structure. ***/
  222.  
  223. char TITLETEXT[] = "VirusX 1.50 by Steve Tibbett";
  224. char text[] = "DF6: Boot Sectors"; /* for display thing */
  225.  
  226. struct NewWindow NewLittleWindow = {
  227.     128,    /* Left, Top, Width, Height */    
  228.     0,        
  229.     309,
  230.     10,        
  231.     0,    /* Frontpen, Backpen */    
  232.     1,        
  233. DISKINSERTED | CLOSEWINDOW | VANILLAKEY | MOUSEBUTTONS | NEWSIZE,    /* IDCMP Flagz */
  234. WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */    
  235.     NULL,        
  236.     NULL,        
  237.     TITLETEXT,    /* My name.  Vous Touchez mon Name, Vous dies. */
  238.     NULL,        
  239.     NULL,        
  240.     0,        
  241.     0,        
  242.     0,        
  243.     0,        
  244.     WBENCHSCREEN,    
  245.     };
  246.  
  247. /*********************Da Beginnin*************************/
  248. main(argc, argv)
  249. int argc, argv;
  250. {
  251. /* Come on, folks, is intuition ever NOT going to be available???? */
  252. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  253.  
  254. /* Same with GfxBase.  If GfxBase is gone, we DESERVE to crash. */
  255. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  256.  
  257. /*  We use the same port/request through the whole program.  Works OK. */
  258. diskport = CreatePort(0,0);
  259. diskreq = CreateStdIO(diskport);
  260.  
  261. LittleWindow = OpenWindow(&NewLittleWindow);
  262. if (LittleWindow == NULL) exit(400L);    /* No memory to open little window! */
  263.  
  264. RP = LittleWindow->RPort;    /* easier than typing Move(LittleWindow->RP*/
  265.  
  266. /* This does some setup stuff, I guess, eh? */
  267. SetUp();
  268.  
  269. /*  Check for Byte Bandit, SCA, Revenge and ByteWarrior in RAM.  */
  270. CheckMemoryForViruses();
  271.  
  272. CheckBlock();
  273.  
  274. DoLittle();    /* The main loop.  Do Little.  Ya. */
  275.  
  276. DeletePort(diskport);
  277. DeleteStdIO(diskreq);
  278. }            
  279.  
  280. /*********************/
  281. DoLittle()
  282. {
  283. register int Code;    /* for storing our IntuiMessage stuff */
  284. register int Class;
  285. register int KG2;    /* KeepGoing 2.  Another booleean. */
  286.  
  287. KG2 = TRUE;
  288.  
  289. SetAPen(RP, 1);
  290. SetBPen(RP, 0);
  291. SetDrMd(RP, JAM2);
  292.  
  293. while (KG2 == TRUE)
  294.     {
  295.     sprintf(titlebuffer, "VirusX: Disks Checked: %d   Disks Installed: %d   Viruses Found: %d", DisksChecked, DisksInstalled, VirusesFound);
  296.     SetWindowTitles(LittleWindow, -1, titlebuffer);
  297.     WaitPort(LittleWindow->UserPort);
  298.     Message = GetMsg(LittleWindow->UserPort);
  299.  
  300.     Class = Message->Class;
  301.     Code = Message->Code;
  302.     ReplyMsg(Message);
  303.     
  304.     if (Class == CLOSEWINDOW) 
  305.         {
  306.         KG2 = FALSE;
  307.         continue;
  308.         };
  309.  
  310.     if (Class == VANILLAKEY)
  311.         {
  312.         int flag;
  313.         flag = ShowAscii(Code);
  314.         if (flag == 1) CheckBlock();
  315.         };
  316.  
  317.     if (Class == DISKINSERTED) CheckBlock();
  318.     };
  319.  
  320. CloseWindow(LittleWindow);
  321. return;
  322. }
  323.  
  324. /************************************************/
  325. /* Opens trackdisk, finds out who's out there,  */
  326. /* and sets Changecount up accordioningly.      */
  327. /************************************************/
  328. SetUp()
  329. {
  330. for (x = 0; x < 4; x++)    /* go thru all 4 possible drives */
  331.     {
  332.     ChangeCount[x] = 1000;
  333.     error = OpenDevice(TDName,x,diskreq,0);
  334.     if (error > 0) 
  335.         {
  336.         ChangeCount[x] = -1;
  337.         };
  338.     };
  339.  
  340. }
  341.  
  342. /*********************************************************/
  343. /* This routine returns which drive changed disks lately */
  344. /*********************************************************/
  345. WhoChanged()
  346. {
  347. int RetVal;    /* The value we'll return */
  348.  
  349. RetVal = -1;    /* return -1 if all else fails */
  350. for (x = 0; x < 4; x++)
  351.     {
  352.     if (ChangeCount[x] == -1) continue;    /* no drive here */
  353.     error = OpenDevice(TDName,x,diskreq,0);
  354.     if (error > 0) continue;    /* no drive here */
  355.     
  356.     diskreq->io_Command = TD_CHANGESTATE;
  357.     DoIO(diskreq);
  358.     if (diskreq->io_Actual != 0) 
  359.         {
  360.         continue;
  361.         };
  362.  
  363.     diskreq->io_Command = TD_CHANGENUM;
  364.     DoIO(diskreq);
  365.     if (diskreq->io_Actual != ChangeCount[x]) 
  366.         {
  367.         RetVal = x;
  368.         ChangeCount[x] = diskreq->io_Actual;
  369.         CloseDevice(diskreq);
  370.         goto Out;
  371.         };
  372.  
  373.     CloseDevice(diskreq);
  374.     };
  375.  
  376. Out:;
  377. return(RetVal);
  378. }
  379.  
  380. /****************************************************************/
  381. /*  Figures out which drive changed disks (using WhoChanged(),  */
  382. /*  And checks it.  Calling this after every DISKINSERTED is OK.*/
  383. /****************************************************************/
  384.  
  385. CheckBlock()
  386. {
  387. /*  How many register vars can I use, anyway? */
  388. register int Sum, Bootable, Virus;
  389. register int a, Unit;
  390. register int SCA, ByteWarrior, Revenge, BBandit;
  391.  
  392. unsigned int *ptr;
  393.  
  394. while ((Unit = WhoChanged()) != -1)
  395.     {
  396.     DisksChecked++;
  397.  
  398.     SCA = FALSE;
  399.     BBandit = FALSE;
  400.     Revenge = FALSE;
  401.     ByteWarrior = FALSE;
  402.  
  403.     /* Unit # to open is returned by "WhoChanged()" up above. */
  404.     if (Unit == -1) return;
  405.     error = OpenDevice(TDName,Unit,diskreq,0);
  406.     if (error > 0) return;
  407.  
  408.     /* I've heard stories that pulling a read request to block zero with a
  409.        length of 1024 will cause the virus to write itself back.  Not taking
  410.        any chances. */
  411.  
  412.     diskreq->io_Command = CMD_READ;
  413.     diskreq->io_Data = diskbuffer;
  414.     diskreq->io_Length = 3*512;
  415.     diskreq->io_Offset = 0;
  416.     DoIO(diskreq);
  417.     if (diskreq->io_Error > 19) return;    /* disk error, lemme out */
  418.  
  419.     diskreq->io_Length = 0;
  420.     diskreq->io_Command = TD_MOTOR;
  421.     DoIO(diskreq);                /* turn off motor */
  422.  
  423.     if (diskreq->io_Error > 19) return;    /* disk error, lemme out */
  424.     CloseDevice(diskreq);
  425.  
  426.     ptr = &diskbuffer[0];
  427.     Sum = 0;
  428.     for (a=0; a<256 /*1024/4 cuz we're dealing with ptr math now*/  ; a++)
  429.         {
  430.         LastSum = Sum;
  431.         Sum = Sum + ptr[a];
  432.         if (LastSum > Sum) Sum++;    /* took me a while to figger this out */
  433.         }
  434.  
  435.     if (Sum != 0) 
  436.         {
  437.         return;    /* if it's not bootable, we DONT want it! */
  438.         };
  439.  
  440.     ptr = &diskbuffer[4];
  441.  
  442.     if (diskbuffer[0x34] == 100)
  443.         if (diskbuffer[0xc4] == 48)
  444.             if (diskbuffer[0xb] == 89)
  445.                 if (diskbuffer[0xf1] == 7)
  446.                     {
  447.                     VirusesFound++;
  448.                     ByteWarrior = TRUE;
  449.                     };
  450.  
  451.     if (diskbuffer[0x2b] == '9')
  452.         if (diskbuffer[0x2c] == '.')
  453.             if (diskbuffer[0x2d] == '8')
  454.                 if (diskbuffer[0x2e] == '7')
  455.                     {
  456.                     VirusesFound++;
  457.                     BBandit = TRUE;    /* 9.87 is part of BBandit Virus */
  458.                     };
  459.  
  460.     /* check specifically for SCA virus */
  461.     if (diskbuffer[8] == 'C')
  462.         if (diskbuffer[9] == 'H')
  463.             if (diskbuffer[10] == 'W')
  464.                     {
  465.                     SCA = TRUE;    /* CHW is part of SCA virus */
  466.                     VirusesFound++;
  467.                     };
  468.  
  469.     if (diskbuffer[0xe] == 'I')
  470.         if (diskbuffer[0xf] == 'D')
  471.             if (diskbuffer[0x10] == '9')
  472.                 if (diskbuffer[0x1a6] == 'f')
  473.                     {
  474.                     Revenge= TRUE;
  475.                     VirusesFound++;
  476.                     };
  477.  
  478.     /* compare boot block with real boot block.  If it's not, notify God. */
  479.     Virus = FALSE;
  480.  
  481.     for (x = 0; x < 39; x++) /* num of bytes in bootblock */
  482.         {
  483.         if (diskbuffer[8+x] != bootblock[8+x])
  484.             {    
  485.             Virus = TRUE;
  486.             };
  487.         };
  488.  
  489.     /* Oh no, a Virus! */
  490.     if (Virus == TRUE) 
  491.         {
  492.         NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
  493.         TEXTPTR[23] = '0'+Unit;
  494.  
  495.         if (SCA == TRUE)
  496.             {
  497.             /* OH NOOOOO, an SCA virus.  Wimpo virus, compared to BBandit 
  498.                but it's a lot nicer code to read. */
  499.             Delay(1);
  500.             error = AutoRequest(LittleWindow, &SCABody, &SCAPos, &SCANeg, 0, 0, 320, 70);
  501.             if (error == TRUE) DoInstall(Unit);    /* user wants it fixed. */
  502.             Delay(1);
  503.             }
  504.         else if (BBandit == TRUE)
  505.             {
  506.             /* The Byte Bandit Virus.  Tricky bugger, he WAS. Cheats, tho. */
  507.             sprintf(CopyText, copystring, (diskbuffer[74]*256)+diskbuffer[75]);
  508.             error = AutoRequest(LittleWindow, &BBDiskbody, &SCAPos, &SCANeg, 0, 0, 380, 80);
  509.             if (error == TRUE) DoInstall(Unit); /* User crying for aid */
  510.             }
  511.         else if (Revenge == TRUE)
  512.             {
  513.             /* Revenge virus.  X rated bugger, lot like Byte Bandit. */
  514.             sprintf(CopyText, copystring, (diskbuffer[0x3f6]*256)+diskbuffer[0x3f7]);
  515.             error = AutoRequest(LittleWindow, &RevDiskbody, &SCAPos, &SCANeg, 0, 0, 380, 80);
  516.             if (error == TRUE) DoInstall(Unit); /* User crying for aid */
  517.             }
  518.         else if (ByteWarrior == TRUE)
  519.             {
  520.             /* Byte Warrior.  Very 'friendly' virus.  Ez to get rid of.  */
  521.             error = AutoRequest(LittleWindow, &ByteWarriorBody, &SCAPos, &SCANeg, 0, 0, 380, 70);
  522.             if (error == TRUE) DoInstall(Unit); /* User crying for aid */
  523.             }
  524.         else 
  525.             {
  526.             /* Probably just a custom boot block (or a new virus...) */
  527.             error = AutoRequest(LittleWindow, &Body1, &Pos, &Neg, 0, 0, 320, 70);
  528.             if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
  529.             }
  530.         };
  531.     };  /* End of While Whochanged */
  532. }
  533.  
  534. /********************************************/
  535. /* This is where the boot code gets changed */
  536. /********************************************/
  537. DoInstall(un)
  538. int un;    /* unit to write to */
  539. {
  540. register int x;
  541. register int Sum;
  542. register int err, a;
  543.  
  544. /* Rewrite disk?  Really?  */
  545. error = AutoRequest(LittleWindow, &REWBody, &REWPos, &REWNeg, 0, 0, 320, 75);
  546. if (error != TRUE) return;    /* user changed his brain. */
  547.  
  548. DisksInstalled++;
  549.  
  550. error = OpenDevice(TDName, un,diskreq,0);
  551. if (error > 0) return;
  552.  
  553. trygain:
  554.  
  555. diskreq->io_Command = TD_PROTSTATUS;
  556. DoIO(diskreq);        /* check if disk is write protected */
  557.  
  558. if (diskreq->io_Actual != 0)
  559.     {
  560.     error = AutoRequest(LittleWindow, &ERRBody, &ERRPos, &ERRNeg, 0, 0, 280, 75);
  561.     if (error == TRUE) /* error is true or false, depending on user */
  562.         {
  563.         goto trygain;
  564.         };
  565.     CloseDevice(diskreq);
  566.     return;    /* unrecoverable write protect error!!!!!!!!! */
  567.     };
  568.  
  569.  
  570. for (x = 0; x < 1024; x++)
  571.     diskbuffer[x] = 0;    /* clear diskbuffer to zero.  clean. */
  572.  
  573. CopyMem(bootblock, diskbuffer, 50); /* Copy it over */
  574.  
  575. /* Write it ! */
  576.  
  577.     {
  578.     error = 0;
  579.     diskreq->io_Length = 1024; /* here we go! */
  580.     diskreq->io_Data = &diskbuffer[0];  
  581.     diskreq->io_Command = CMD_WRITE;
  582.     diskreq->io_Offset = 0L;
  583.     DoIO(diskreq);
  584.     error = diskreq->io_Error;
  585.     };
  586.  
  587. if (error < 19)
  588.     {
  589.     diskreq->io_Command = CMD_UPDATE;    /* flush buffer to disk */
  590.     DoIO(diskreq);
  591.     error = diskreq->io_Error;
  592.     };
  593.  
  594. if (error < 19) 
  595.     {
  596.     Delay(5);
  597.     diskreq->io_Length = 0;
  598.     diskreq->io_Command = ETD_MOTOR;
  599.     DoIO(diskreq);                /* turn off motor */
  600.     error = diskreq->io_Error;
  601.     };
  602.  
  603. CloseDevice(diskreq);
  604.  
  605. if (error > 19) 
  606.     {
  607.     SetWindowTitles(LittleWindow, "Error, Nothing Done.", -1);
  608.     } 
  609.     else
  610.     {
  611.     SetWindowTitles(LittleWindow, "Disk Healed.", -1);
  612.     };
  613.  
  614. Delay(150);
  615. SetWindowTitles(LittleWindow, TITLETEXT, -1);
  616. }
  617.  
  618.  
  619. /************************/
  620.  
  621. CheckMemoryForViruses()
  622. {
  623. int VirusBase;    /* ick, whatta name! */
  624. int Temp;
  625. struct ExecBase *ExecBase;
  626. unsigned int *LongMemPointer;    /* Used for reading FROM memory */
  627. unsigned short *loc;
  628. unsigned int *ptr;
  629.  
  630. ExecBase = OpenLibrary("exec.library", 0);
  631.  
  632.  
  633. /**************- Check for Byte Bandit (look at TD Vector) *************/
  634. /*  (Byte Bandit isn't at a fixed location.  Depends on your RAM.      */
  635.  
  636. /* LongMemPointer = &trackdisk.device */
  637. LongMemPointer = FindName(&ExecBase->DeviceList, TDName);
  638. Temp = LongMemPointer;
  639. Temp = Temp - 0x1c;
  640. LongMemPointer = Temp; 
  641. VirusBase = (*LongMemPointer) - 0x1b8;
  642. LongMemPointer = VirusBase;
  643.  
  644. if (*LongMemPointer == ('D'<<24) + ('O'<<16) + ('S'<<8))    /* klugo */
  645.     {
  646.     /* Ok, so we don't really remove it from memory, but we DO render
  647.            it harmless. */
  648.     Disable();
  649.     loc = VirusBase+0xaa;
  650.     loc[0] = 0x4e71;
  651.     loc[1] = 0x4e71;
  652.     loc[2] = 0x4e71;
  653.     loc[3] = 0x4e71;         /* NOP's */
  654.  
  655.     loc = VirusBase+0x1c2;
  656.     loc[0] = 0x6000;        /* Change Bxx to BRA */
  657.  
  658.     loc = VirusBase+0x2d2;
  659.     loc[0] = 0x6000;
  660.  
  661.     loc = VirusBase+0x388; loc[0] = 0x4e75;  /* Make sure it doesn't come back */
  662.     loc = VirusBase + 0x3ea;  loc[0] = 0;     /* Kill resident matchword */
  663.     loc = VirusBase; loc[0] = 0; 
  664.     Enable();
  665.     error = AutoRequest(LittleWindow, &BBMem3, &BBMPos, &BBMPos, 0, 0, 395, 78);
  666.     };
  667.  
  668. /****************- Look for Revenge Virus (at $7e000) ****************/
  669. if (ExecBase->CoolCapture == 516192)
  670.     {
  671.     /* Fix the CoolCapture vector */
  672.     ExecBase->CoolCapture = 0;
  673.     
  674.     /* Get rid of his DOS\0 in memory */
  675.     loc = 0x7e000; loc[0] = 0;
  676.  
  677.     /* Patch his DoIO() wedge */
  678.     Disable();
  679.     loc = 0x7e1e0;
  680.     loc[0] = 0x4ef9;
  681.     loc[1] = 0x7;
  682.     loc[2] = 0xe066;
  683.  
  684.     /* Patch his Interrupt wedge */
  685.     loc = 0x7e2da;
  686.     loc[0] = 0x4ef9;
  687.     loc[1] = 0x7;
  688.     loc[2] = 0xe06C;
  689.     Enable();
  690.     error = AutoRequest(LittleWindow, &RevMem, &BBMPos, &BBMPos, 0, 0, 395, 78);
  691.     };
  692.  
  693. /******************** See if SCA is in RAM ***************************/
  694. if (ExecBase->CoolCapture == 0x7ec3e)
  695.     {
  696.     ExecBase->CoolCapture = 0;
  697.     error = AutoRequest(LittleWindow, &SCAMem, &BBMPos, &BBMPos, 0, 0, 395, 78);
  698.     };
  699.     
  700. /********************* Check for Byte Warrior ************************/
  701. ptr = 0x7f800;
  702. if (ptr[0] == ('D'<<24) + ('O'<<16) + ('S'<<8))
  703.     {
  704.     ptr = 0x7f954;
  705.     if (ptr[0] = 0x4afc)
  706.         {
  707.         ptr[0] = 0;        /* Kill resident matchtag */
  708.         Forbid();
  709.         
  710.         loc = 0x7f972;
  711.         loc[0] = 0x4ef9; 
  712.         loc[1] = 0x00fc;
  713.         loc[2] = 0x06dc;    /* jump right into the 1.2 ROMs. Ow. */
  714.         
  715.         loc = 0x7f800;
  716.         loc[0] = 0;
  717.         Permit();
  718.         error = AutoRequest(LittleWindow, &ByteWarriorMem, &BBMPos, &BBMPos, 0, 0, 395, 78);
  719.         };
  720.     };
  721.  
  722. CloseLibrary(ExecBase);
  723. }
  724.  
  725.  
  726. /**************************************************************/
  727. /*  This is the routine that displauys a block as ASCII text. */
  728. /**************************************************************/
  729. ShowAscii(key)
  730. int key;
  731. {
  732. char linebuffer[80];
  733. int drive;
  734. int x,y;
  735. int deltax, deltay;
  736. int a,b;
  737. int FLAG=0;
  738.  
  739. struct RastPort *RP;
  740. RP = LittleWindow->RPort;
  741.  
  742. drive = key - '0';
  743.  
  744. if ((drive < 0) || (drive > 3) || (ChangeCount[drive] == -1)) return;
  745.  
  746. error = OpenDevice(TDName,drive,diskreq,0);
  747. if (error > 0) return;
  748.  
  749. /*  Read in the selected 1K boot blok */
  750. diskreq->io_Command = CMD_READ;
  751. diskreq->io_Data = diskbuffer;
  752. diskreq->io_Length = 3*512;
  753. diskreq->io_Offset = 0;
  754. DoIO(diskreq);
  755. if (diskreq->io_Error > 0) return;    /* disk error, lemme out */
  756.  
  757. diskreq->io_Length = 0;
  758. diskreq->io_Command = TD_MOTOR;
  759. DoIO(diskreq);                /* turn off motor */
  760. if (diskreq->io_Error > 0) return;    /* disk error, lemme out */
  761.  
  762. CloseDevice(diskreq);
  763.  
  764. /* save the amount we moved the window */
  765. deltax = LittleWindow->LeftEdge;
  766. deltay = LittleWindow->TopEdge;
  767.  
  768. MoveWindow(LittleWindow, -deltax, -deltay);
  769.  
  770. SizeWindow(LittleWindow, 278, 160);
  771. WaitForNewSize();
  772.  
  773. SetAPen(RP, 3);
  774. Move(RP, 14+(12*8), 165);
  775. Text(RP, "Block 0", 7);
  776. Move(RP, 324+(12*8), 165);
  777. Text(RP, "Block 1", 7);
  778. SetAPen(RP, 1);
  779.  
  780. text[2] = key;
  781. SetWindowTitles(LittleWindow, text, -1);
  782.  
  783. x=0; y=0;
  784.  
  785. SetAPen(RP, 1);
  786. SetDrMd(RP, JAM2);
  787.  
  788. for (a=0; a<512; a=a+32)
  789.     {
  790.     Move(RP, 10+(x*8), 20+(y*9));
  791.     Text(RP, &diskbuffer[a], 32);
  792.  
  793.     Move(RP, 320+(x*8), 20+(y*9));
  794.     Text(RP, &diskbuffer[a+512], 32);
  795.     y++;
  796.     };
  797.  
  798. Wait(1<<LittleWindow->UserPort->mp_SigBit);
  799. Message = GetMsg(LittleWindow->UserPort);
  800.  
  801. /*  If a disk was inserted, we want CheckBlock() to happen later on some time */
  802. if (Message->Class == DISKINSERTED) FLAG=1;
  803. ReplyMsg(Message);
  804.  
  805. returner:
  806. SizeWindow(LittleWindow, -278, -160);
  807. SetWindowTitles(LittleWindow, TITLETEXT, -1);
  808. WaitForNewSize();
  809.  
  810. /* deltas plus current position, in case dude moved the window */
  811. MoveWindow(LittleWindow, deltax+(-LittleWindow->LeftEdge), deltay+(-LittleWindow->TopEdge));
  812. Delay(2);
  813. return(FLAG);
  814. }
  815.  
  816.  
  817. /*  
  818.   When you do a SizeWindow() command, you have to wait for a NEWSIZE
  819.   IntuiMessage before drawing in it.  That's all this routine does.
  820.  */
  821. WaitForNewSize()
  822. {
  823. while (TRUE)
  824.     {
  825.     WaitPort(LittleWindow->UserPort);
  826.     Message = GetMsg(LittleWindow->UserPort);
  827.     if (Message->Class != NEWSIZE)
  828.         {
  829.         ReplyMsg(Message);
  830.         continue;
  831.         };
  832.     ReplyMsg(Message);
  833.     break;
  834.     };
  835. }
  836.